<?php

namespace app\utils;

use app\utils\Types;

class Format {

    public $types;

    public $split_regex;

    public function __construct($types)
    {
        $this->types = $types ?? self::showTypes();
        $tmp = [];
        foreach($this->types as $type) {
            foreach($type as $split) {
                $tmp[] = $split['regex'];
            }
        }
        $this->split_regex = '/(?:' . implode('|', $tmp) . ')/ims';
    }

    public function run($input) {
        // 2. (   ).  替换为 \paren

        $input = preg_replace('/\(\s*\)\.?/', '\paren', $input);

        
        preg_match_all($this->split_regex, $input, $matches);
        $input = preg_split($this->split_regex, $input);

        $types = [];

        foreach($matches[0] as $m) {
            $types[] = $this->getType($m);
        }


        $output = '';
        foreach($input as $key => $item) {
            if($key == 0) continue;
            $output .= $this->format($item, $types[$key - 1]) . "\n\n";
        }

        return $output;
    }

    public function getType($str) {
        foreach($this->types as $key => $types) {
            foreach($types as $type) {
                if(preg_match('/' . $type['regex'] . '/', $str)) {
                    return $key;
                }
            }
        }
    }

    public function format($content, $type) {
        $content = trim($content);
        switch($type) {
            case 'answer':
                return <<<EOL
                \\begin{answer}
                $content
                \\end{answer}
                EOL;
                break;
            case 'solution':
                return <<<EOL
                \\begin{solution}
                $content
                \\end{solution}
                EOL;
                break;
            case 'question':
                // $content = preg_replace('/\d+\.\s*/', '', $content);
                $content = $this->format_choice($content);
                return <<<EOL
                \\begin{example}
                $content
                \\end{example}
                EOL;
                break;
            default:
                return $content;
                break;
        }
    }

    public function format_choice($content) {
        $lines = explode("\n", $content);
        foreach($lines as &$line) {
            if(preg_match('/^\(?[A-Z]\)?\.?\s*/', $line, $matches)) {
                $line = '#@' . trim($line, ' \n\r\t\v\0。') . '@#';
            }
        }
        $content = implode("\n", $lines);
        $content = preg_replace_callback('/#@(.*)@#/ims', function($matches) {
            $tmp = $matches[0];
            return preg_replace('/\(?[A-Z]\)?\.?\s*/', "\n\\item ", $tmp);
        }, $content);

        $content = preg_replace('/#@(.*)@#/ims', "\\begin{choices}\n#@$1@#\n\\end{choices}", $content);

        $content = str_replace(['#@', '@#'], '', $content);

        $content = preg_replace('/(?:\s*\n){2,}/', "\n", $content);

        return $content;
    }

    public static function showTypes() {
        return Types::$types;
    }
}